/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * TelaSimulador.java
 *
 * Created on 27/08/2008, 10:43:00
 */

package sintelo.visao;

import java.awt.Point;
import javax.swing.JViewport;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import sintelo.gerador.GeradorReconhecedores;
import sintelo.reconhecedor.ErroAnalise;
import sintelo.reconhecedor.ErroLexico;
import sintelo.reconhecedor.Semantico;
import sintelo.reconhecedor.Token;
import sintelo.simulador.ObservadorLexico;
import sintelo.simulador.Simulador;
import sintelo.visao.realce.Realce;
import sintelo.visao.realce.Realces;

/**
 *
 * @author phireis
 */
public class TelaSimulador extends javax.swing.JFrame {

    private Realce realce;
    private SimpleAttributeSet centro;

    private Semantico semantico;
    private ObservadorLexico observadorLexico;
    private Simulador simulador;
        
    private DefaultTableModel tabelaTokens;
    private DefaultTableModel tabelaAcoes;


    private ErroAnalise erro;

    /** Creates new form TelaSimulador */
    public TelaSimulador(final GeradorReconhecedores gerador) {
        initComponents();

        realce = Realces.getRealceGramatica();
        centro = new SimpleAttributeSet();
        StyleConstants.setAlignment(centro, StyleConstants.ALIGN_CENTER);

        tabelaTokens = (DefaultTableModel) tblTokens.getModel();
        tabelaAcoes = (DefaultTableModel) tblAcoes.getModel();

        semantico = new Semantico() {
            public void executa(int acao, Token token) {
                Object[] linha = {"#" + acao, token.getTexto(), token.getPosicao()};
                tabelaAcoes.addRow(linha);
            }
        };

        observadorLexico = new ObservadorLexico() {
            public void tokenReconhecido(Token t) {
                String tipo = gerador.getToken(t.getNumero());
                Object[] linha = {tipo, t.getTexto(), t.getPosicao()};
                tabelaTokens.addRow(linha);
            }
        };

        simulador = new Simulador(gerador, semantico, observadorLexico);

        setGramatica(simulador.getGramatica());        

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        barraFerramentas = new javax.swing.JToolBar();
        btnInicia = new javax.swing.JButton();
        btnAvanca = new javax.swing.JButton();
        btnTermina = new javax.swing.JButton();
        jDesktopPane1 = new javax.swing.JDesktopPane();
        framePilha = new javax.swing.JInternalFrame();
        scrollPilha = new javax.swing.JScrollPane();
        panelPilha = new javax.swing.JPanel();
        txtPilha = new javax.swing.JTextPane();
        frameGramatica = new javax.swing.JInternalFrame();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtGramatica = new javax.swing.JTextPane();
        frameTokens = new javax.swing.JInternalFrame();
        jScrollPane3 = new javax.swing.JScrollPane();
        tblTokens = new javax.swing.JTable();
        frameAcoes = new javax.swing.JInternalFrame();
        jScrollPane4 = new javax.swing.JScrollPane();
        tblAcoes = new javax.swing.JTable();
        frameEntrada = new javax.swing.JInternalFrame();
        jScrollPane5 = new javax.swing.JScrollPane();
        txtEntrada = new javax.swing.JTextPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Simulação LL(1)");

        barraFerramentas.setFloatable(false);
        barraFerramentas.setRollover(true);

        btnInicia.setText("Inicia");
        btnInicia.setFocusable(false);
        btnInicia.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnInicia.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnInicia.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnIniciaActionPerformed(evt);
            }
        });
        barraFerramentas.add(btnInicia);

        btnAvanca.setText("Avança");
        btnAvanca.setFocusable(false);
        btnAvanca.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnAvanca.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnAvanca.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAvancaActionPerformed(evt);
            }
        });
        barraFerramentas.add(btnAvanca);

        btnTermina.setText("Termina");
        btnTermina.setFocusable(false);
        btnTermina.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnTermina.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnTermina.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnTerminaActionPerformed(evt);
            }
        });
        barraFerramentas.add(btnTermina);

        getContentPane().add(barraFerramentas, java.awt.BorderLayout.PAGE_START);

        jDesktopPane1.setBackground(new java.awt.Color(0, 153, 204));

        framePilha.setIconifiable(true);
        framePilha.setMaximizable(true);
        framePilha.setResizable(true);
        framePilha.setTitle("Pilha de expansão");
        framePilha.setMinimumSize(new java.awt.Dimension(50, 200));
        framePilha.setVisible(true);

        scrollPilha.setAutoscrolls(true);

        panelPilha.setAutoscrolls(true);
        panelPilha.setLayout(new java.awt.BorderLayout());

        txtPilha.setEditable(false);
        txtPilha.setAutoscrolls(false);
        txtPilha.setOpaque(false);
        panelPilha.add(txtPilha, java.awt.BorderLayout.PAGE_END);

        scrollPilha.setViewportView(panelPilha);

        framePilha.getContentPane().add(scrollPilha, java.awt.BorderLayout.CENTER);

        framePilha.setBounds(30, 20, 130, 320);
        jDesktopPane1.add(framePilha, javax.swing.JLayeredPane.DEFAULT_LAYER);

        frameGramatica.setIconifiable(true);
        frameGramatica.setMaximizable(true);
        frameGramatica.setResizable(true);
        frameGramatica.setTitle("Gramática");
        frameGramatica.setMinimumSize(new java.awt.Dimension(150, 150));
        frameGramatica.setVisible(true);

        txtGramatica.setEditable(false);
        jScrollPane1.setViewportView(txtGramatica);

        frameGramatica.getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        frameGramatica.setBounds(300, 300, 430, 220);
        jDesktopPane1.add(frameGramatica, javax.swing.JLayeredPane.DEFAULT_LAYER);

        frameTokens.setIconifiable(true);
        frameTokens.setMaximizable(true);
        frameTokens.setResizable(true);
        frameTokens.setTitle("Tokens");
        frameTokens.setMinimumSize(new java.awt.Dimension(150, 150));
        frameTokens.setVisible(true);

        jScrollPane3.setAutoscrolls(true);

        tblTokens.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Tipo", "Texto", "Posição"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tblTokens.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        tblTokens.getTableHeader().setReorderingAllowed(false);
        jScrollPane3.setViewportView(tblTokens);

        frameTokens.getContentPane().add(jScrollPane3, java.awt.BorderLayout.CENTER);

        frameTokens.setBounds(180, 40, 250, 250);
        jDesktopPane1.add(frameTokens, javax.swing.JLayeredPane.DEFAULT_LAYER);

        frameAcoes.setIconifiable(true);
        frameAcoes.setMaximizable(true);
        frameAcoes.setResizable(true);
        frameAcoes.setTitle("Ações semânticas");
        frameAcoes.setMinimumSize(new java.awt.Dimension(150, 150));
        frameAcoes.setVisible(true);

        tblAcoes.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Ação", "Token", "Posição"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tblAcoes.getTableHeader().setReorderingAllowed(false);
        jScrollPane4.setViewportView(tblAcoes);

        frameAcoes.getContentPane().add(jScrollPane4, java.awt.BorderLayout.CENTER);

        frameAcoes.setBounds(30, 350, 250, 180);
        jDesktopPane1.add(frameAcoes, javax.swing.JLayeredPane.DEFAULT_LAYER);

        frameEntrada.setIconifiable(true);
        frameEntrada.setMaximizable(true);
        frameEntrada.setResizable(true);
        frameEntrada.setTitle("Entrada");
        frameEntrada.setVisible(true);

        jScrollPane5.setViewportView(txtEntrada);

        frameEntrada.getContentPane().add(jScrollPane5, java.awt.BorderLayout.CENTER);

        frameEntrada.setBounds(450, 40, 320, 230);
        jDesktopPane1.add(frameEntrada, javax.swing.JLayeredPane.DEFAULT_LAYER);

        getContentPane().add(jDesktopPane1, java.awt.BorderLayout.CENTER);

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-800)/2, (screenSize.height-600)/2, 800, 600);
    }// </editor-fold>//GEN-END:initComponents

    private void btnIniciaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnIniciaActionPerformed
        novaAnalise();
    }//GEN-LAST:event_btnIniciaActionPerformed

    private void btnAvancaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAvancaActionPerformed
        avanca();
    }//GEN-LAST:event_btnAvancaActionPerformed

    private void btnTerminaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminaActionPerformed
        termina();
    }//GEN-LAST:event_btnTerminaActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JToolBar barraFerramentas;
    private javax.swing.JButton btnAvanca;
    private javax.swing.JButton btnInicia;
    private javax.swing.JButton btnTermina;
    private javax.swing.JInternalFrame frameAcoes;
    private javax.swing.JInternalFrame frameEntrada;
    private javax.swing.JInternalFrame frameGramatica;
    private javax.swing.JInternalFrame framePilha;
    private javax.swing.JInternalFrame frameTokens;
    private javax.swing.JDesktopPane jDesktopPane1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JPanel panelPilha;
    private javax.swing.JScrollPane scrollPilha;
    private javax.swing.JTable tblAcoes;
    private javax.swing.JTable tblTokens;
    private javax.swing.JTextPane txtEntrada;
    private javax.swing.JTextPane txtGramatica;
    private javax.swing.JTextPane txtPilha;
    // End of variables declaration//GEN-END:variables


    private void marcaErro(ErroAnalise e){
        erro = e;
        Mensagens.alerta(this, e.getMessage(), "Erro na análise");
        txtEntrada.setCaretPosition(e.getPosicao());
    }

    public boolean novaAnalise(){
        try{
            erro = null;
            tabelaAcoes.setRowCount(0);
            tabelaTokens.setRowCount(0);
            String entrada = txtEntrada.getText();
            simulador.novaSimulacao(entrada); 
            setPilha(simulador.getPilha());
            return true;
        }catch(ErroLexico e){
            e.printStackTrace();
            marcaErro(e);
            return false;
        }
    }

    public boolean avanca(){
        if(erro != null){
            Mensagens.alerta(this, erro.getMessage(), "Erro na análise");
            return false;
        }
        if(simulador.getSintatico() == null){
            return novaAnalise();
        }
        try{
            if(!simulador.analiseTerminou()){
                simulador.avanca();
                setPilha(simulador.getPilha());
                return true;
            }
            else{
                Mensagens.informa(this, "Análise terminada com sucesso!");
                return false;
            }
        }catch(ErroAnalise e){
            e.printStackTrace();
            marcaErro(e);
            return false;
        }
    }
    
    public void termina(){
        if(simulador != null){
            if(!simulador.analiseTerminou() && erro == null){
                while(avanca());
            }
        }
    }
    
    public void setPilha(String s){
        txtPilha.setParagraphAttributes(centro, true);
        txtPilha.setText(s);
        realce.aplica(txtPilha);        
    }
    
    private void scrollUp(){
        JViewport view = scrollPilha.getViewport();
        Point p = view.getViewPosition();
        p.y = 0;
        view.setViewPosition(p);
    }

    public void setGramatica(String s){
        txtGramatica.setText(s);
        realce.aplica(txtGramatica);
    }
    

}
